package com.ning.api.client.item;
import java.io.IOException;
import java.util.HashMap;
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.map.ObjectMapper;
/**
* Container used for containing and accessing sub-resources that are associated with
* and shared by actual content items.
*/
public class SubResources
{
/**
* Object mapper we use if sub-resource binding is needed
*/
protected final ObjectMapper objectMapper;
protected final JsonNode resources;
/**
* If and when a sub-resource gets bound, we will retain result to avoid
* excessive deserialization costs
*/
private transient HashMap<String, Object> boundResources;
public SubResources(ObjectMapper m, JsonNode r)
{
objectMapper = m;
resources = r;
}
public <RT> RT findOrLoadResource(Class<RT> type, String id)
{
return findOrLoadResource(type, id, null);
}
public <RT> RT findOrLoadResource(Class<RT> type, String id, RT instance)
{
RT value = findResource(type, id);
if (value == null) {
value = loadResource(type, id, instance);
}
return value;
}
/**
* Method for finding already resolved sub-resource instance by id
*/
protected <RT> RT findResource(Class<RT> type, String id)
{
if (boundResources != null) {
Object ob = boundResources.get(id);
if (ob != null) { // sanity check
if (!(ob instanceof Author)) {
throw new IllegalArgumentException("Type problem: sub-resource '"+id+"' not of type "
+type.getSimpleName()+", but of type "+ob.getClass().getSimpleName());
}
@SuppressWarnings("unchecked")
RT result = (RT) ob;
return result;
}
}
return null;
}
/**
* Method for loading specified resources
*/
protected <RT> RT loadResource(Class<RT> type, String id, RT instance)
{
if (resources == null || id == null) {
return null;
}
JsonNode entry = resources.get(id);
if (entry == null) {
return null;
}
// Ok: should be an object... if not, indicate error
if (!entry.isObject()) {
throw new IllegalArgumentException("Corrupt or malformed data: "+type.getSimpleName()+" data for '"+id
+"' not a JSON object but "+entry.asToken());
}
// Then try binding
try {
if (instance == null) {
instance = objectMapper.treeToValue(entry, type);
} else {
objectMapper.updatingReader(instance).readValue(entry.traverse());
}
} catch (IOException e) {
throw new IllegalArgumentException("Corrupt or malformed data: author data for '"+id
+"' could not be bound, problem: "+e.getMessage());
}
if (boundResources == null) {
boundResources = new HashMap<String,Object>();
}
boundResources.put(id, instance);
return instance;
}
}